package com.ete.lib.upload.logZip

import android.content.Context
import android.view.View
import android.view.Window
import androidx.annotation.StringRes
import com.blankj.utilcode.util.*
import com.ete.lib.upload.R
import com.ete.lib.upload.UploadConstant
import com.ete.lib.upload.UploadManager
import com.ete.lib.upload.bean.CommonDialogEntry
import com.ete.lib.upload.bean.UploadEntry
import com.ete.lib.upload.net.api.UploadService
import com.ete.lib.upload.net.bean.BaseResponse
import com.ete.lib.upload.net.exception.ExceptionTranslate
import com.ete.lib.upload.net.http.RetrofitClient
import com.ete.lib.upload.net.progress.IProgressListener
import com.ete.lib.upload.ui.CommonDialog
import com.ete.lib.upload.ui.InputDescriptionDialog
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.File

/**
 * Author:LiXian
 * <p>
 * Desc:上报App日志工具类
 * Version:1.0
 * date 2024/1/8 17:39
 */
object UploadLogUtil {

    lateinit var mUploadEntry: UploadEntry

    private val mZipLogDir by lazy {
        SDCardUtils.getSDCardPathByEnvironment() + File.separator +
                "Download" + File.separator + AppUtils.getAppName()
    }

    @JvmStatic
    fun init(mUploadEntry: UploadEntry) {
        UploadLogUtil.mUploadEntry = mUploadEntry
        Utils.init(mUploadEntry.mApp)
    }

    /**
     * 删除压缩文件
     */
    @JvmStatic
    fun deleteAppZipLogFile() {
        FileUtils.deleteFilesInDir(mZipLogDir)
        ToastUtils.showShort("日志删除成功")
    }

    /**
     * 是否有压缩包
     */
    @JvmStatic
    fun isHadAppZipLogFile(): Boolean {
        return getAppZipLogFile() != null
    }

    /**
     * 获取日志压缩包
     */
    @JvmStatic
    fun getAppZipLogFile(): File? {
        val isDir = FileUtils.isDir(mZipLogDir)
        if (!isDir) return null
        val mFiles = File(mZipLogDir).listFiles()
        if (mFiles.isNullOrEmpty()) return null
        val extension = FileUtils.getFileExtension(mFiles[0])
        if (extension == UploadConstant.ZIP_FILE_EXTENSION) {
            return mFiles[0]
        }
        return null
    }

    @JvmStatic
    fun getString(@StringRes res: Int): String {
        return mUploadEntry.mApp.getString(res)
    }

    /**
     * 硬件日志文件上传
     */
    @JvmStatic
    fun uploadAppLogFile() {
        val mCallback = { isNetwork: Boolean ->
            if (isNetwork) {
                val isWifiNetwork = NetworkUtils.isWifiConnected()
                if (isWifiNetwork) {
                    LogUtils.d(UploadManager.TAG, "WIFI网络，压缩APP目录")
                    showInputDescriptionDialog()
                } else {
                    LogUtils.d(UploadManager.TAG, "移动网络，流量使用过大提醒")
                    showNotWifiDialog()
                }
            } else {
                LogUtils.d(UploadManager.TAG, "网络不可用！")
                ToastUtils.showShort(R.string.upload_not_network)
            }
        }
        checkNetwork(mCallback)
    }

    /**
     * 问题描述Dialog
     */
    @JvmStatic
    private fun showInputDescriptionDialog() {
        val mContext = ActivityUtils.getTopActivity() ?: return
        val mInputDialog = InputDescriptionDialog(mContext, mCallback = {
            startZipFileDir(it)
        })
        mInputDialog.initDialog()
        mInputDialog.show()
    }

    /**
     * 正式上传日志
     */
    @JvmStatic
    private fun realUploadFile(mDialogDialog: CommonDialog?, mZipPath: String, mDescription: String) {
        LogUtils.d(UploadManager.TAG, "正式上传日志压缩包mZipPath:[$mZipPath]，mDescription:[$mDescription]")
        RetrofitClient.clearParameter()
        val parameter: HashMap<String, RequestBody> = RetrofitClient.addParameter("deviceId", mUploadEntry.deviceId)
            .addParameter("appType", mUploadEntry.mAppType)
            .addParameter("description", mDescription)
            .addParameter("uploadFile", File(mZipPath))
            .builder()
        val mCallback = object : Callback<BaseResponse<Boolean>> {
            override fun onResponse(call: Call<BaseResponse<Boolean>>, response: Response<BaseResponse<Boolean>>) {
                mDialogDialog?.dismiss()
                if (!response.isSuccessful) {
                    LogUtils.d(UploadManager.TAG, "上传日志，请求服务器错误: ${response.message()}")
                    ToastUtils.showShort("请求服务器错误: ${response.message()}")
                    return
                }
                val result = response.body()
                if (result == null) {
                    LogUtils.d(UploadManager.TAG, "上传日志，服务器响应为空")
                    ToastUtils.showShort("服务器响应为空")
                    return
                }
                val isSuccess = result.succ
                if (isSuccess == null || !isSuccess) {
                    LogUtils.d(UploadManager.TAG, ("上传日志，" + (result.msg ?: "请求服务器错误")))
                    ToastUtils.showShort(result.msg ?: "请求服务器错误")
                    return
                }
                val isUploadSuccess = result.data
                if (isUploadSuccess == null || !isUploadSuccess) {
                    LogUtils.d(UploadManager.TAG, "日志上传失败")
                    ToastUtils.showShort("日志上传失败")
                    return
                }
                LogUtils.d(UploadManager.TAG, "日志上传成功，删除压缩包mZipPath:[$mZipPath]")
                FileUtils.delete(mZipPath)
                ToastUtils.showShort("日志上传成功")
            }

            override fun onFailure(call: Call<BaseResponse<Boolean>>, t: Throwable) {
                t.printStackTrace()
                mDialogDialog?.dismiss()
                val message = ExceptionTranslate.translateException(t).message
                LogUtils.d(UploadManager.TAG, "日志上传错误message:[$message]")
                ToastUtils.showShort(message)
            }
        }
        val mProgress = object : IProgressListener {
            override fun onStart() {
                LogUtils.d(UploadManager.TAG, "开始上传日志")
                ThreadUtils.runOnUiThread {
                    val mTitle = mUploadEntry.mApp.getString(R.string.upload_zip_upload_log)
                    val mContent = mUploadEntry.mApp.getString(R.string.upload_zip_uploading, "0/100")
                    if (mDialogDialog?.isShowing == false) {
                        mDialogDialog.show()
                    }
                    mDialogDialog?.updateTitle(mTitle)
                    mDialogDialog?.updateContent(mContent)
                }
            }

            override fun onProgress(progress: Int) {
                LogUtils.d(UploadManager.TAG, "上传日志进度progress:[$progress]")
                ThreadUtils.runOnUiThread {
                    val mContent = mUploadEntry.mApp.getString(R.string.upload_zip_uploading, "${progress}/100")
                    mDialogDialog?.updateContent(mContent)
                }
            }

            override fun onFinish() {
                LogUtils.d(UploadManager.TAG, "上传日志完成")
                ThreadUtils.runOnUiThread {
                    mDialogDialog?.dismiss()
                }
            }
        }
        RetrofitClient.createRequestService(UploadService::class.java, mProgress)
            .uploadLogFile(parameter).enqueue(mCallback)
    }

    /**
     * 开始压缩App日志目录
     */
    @JvmStatic
    private fun startZipFileDir(mDescription: String = "") {
        val mDialogDialog = getCommonDialog(
                mTitle = R.string.upload_zip_app_dir,
                mContent = R.string.upload_zip_progress,
                isShowCancel = false,
                isShowSure = false,
                isOutTouchCancel = false,
                isShowClose = false,
                mCallback = { startZipFileDir(mDescription) }
        )
        val mZipFile: File? = getAppZipLogFile()
        if (mZipFile != null) {
            val mFilePath = mZipFile.path
            LogUtils.d(UploadManager.TAG, "本地存在App目录压缩文件mFilePath:[$mFilePath]")
            realUploadFile(mDialogDialog, mFilePath, mDescription)
        } else {
            FileUtils.createOrExistsDir(mZipLogDir)
            val toZipPath = mZipLogDir + File.separator + System.currentTimeMillis() +
                    ".${UploadConstant.ZIP_FILE_EXTENSION}"
            LogUtils.d(UploadManager.TAG, "本地不存在App目录压缩文件，打包压缩文件toZipPath:[$toZipPath]")
            val mCallback = object : IZipCallback {
                override fun onStart() {
                    LogUtils.d(UploadManager.TAG, "开始打包App目录压缩文件")
                    val mContent = mUploadEntry.mApp.getString(R.string.upload_zip_progress, "0/100")
                    mDialogDialog?.updateContent(mContent)
                    mDialogDialog?.show()
                }

                override fun onProgress(progress: Int) {
                    LogUtils.d(UploadManager.TAG, "打包App目录压缩文件进度progress:[$progress]")
                    val mContent = mUploadEntry.mApp.getString(R.string.upload_zip_progress, "${progress}/100")
                    mDialogDialog?.updateContent(mContent)
                }

                override fun onError(code: Int, msg: String) {
                    LogUtils.d(UploadManager.TAG, "打包App目录压缩文件错误msg:[$msg]")
                    mDialogDialog?.dismiss()
                    ToastUtils.showShort(msg)
                }

                override fun onSuccess(scrPath: String, zipPath: String) {
                    LogUtils.d(UploadManager.TAG, "打包App目录压缩文件成功scrPath:[$scrPath]，zipPath:[$zipPath]")
                    val mContent = mUploadEntry.mApp.getString(R.string.upload_zip_success)
                    mDialogDialog?.updateContent(mContent)
                    realUploadFile(mDialogDialog, zipPath, mDescription)
                }
            }
            ZipFileUtil.zipDirFile(mUploadEntry.mAppDir, toZipPath, mCallback, mUploadEntry.zipPassword)
        }
    }

    /**
     * 非wifi提醒
     */
    @JvmStatic
    private fun showNotWifiDialog() {
        val mDialogDialog = getCommonDialog(
                mTitle = R.string.upload_network_tip,
                mContent = R.string.upload_network_tip,
                mCallback = { showInputDescriptionDialog() }
        )
        mDialogDialog?.show()
    }

    @JvmStatic
    private fun getCommonDialog(
            mTitle: Int, mContent: Int,
            isShowSure: Boolean = true,
            isShowCancel: Boolean = true,
            isOutTouchCancel: Boolean = true,
            isShowClose: Boolean = true,
            mCallback: () -> Unit): CommonDialog? {
        val mContext: Context = ActivityUtils.getTopActivity() ?: return null
        val mDialogEntry = CommonDialogEntry(
                mContext = mContext,
                mStyle = mUploadEntry.mAppDialogStyle,
                mTitle = mContext.getString(mTitle),
                mContent = mContext.getString(mContent),
                themeColor = mUploadEntry.mAppThemeColor,
                isOutTouchCancel = isOutTouchCancel,
                isShowSure = isShowSure,
                isShowCancel = isShowCancel,
                isShowClose = isShowClose,
                mSureCallback = {
                    mCallback.invoke()
                    true
                }
        )
        val dialog = CommonDialog(mDialogEntry)
        dialog.initDialog()
        return dialog
    }

    /**
     * 检测是否有网
     */
    @JvmStatic
    private fun checkNetwork(mCallback: (Boolean) -> Unit) {
        val mNetwork = Utils.Consumer<Boolean> {
            mCallback.invoke(it)
        }
        NetworkUtils.isAvailableAsync(mNetwork)
    }

    @JvmStatic
    fun getDialogWidth(rate: Float): Int {
        val mScreenWidth = ScreenUtils.getScreenWidth() - SizeUtils.dp2px(24F)
        val mScreenHeight = ScreenUtils.getScreenHeight() - SizeUtils.dp2px(24F)
        val mWidth: Int = if (mScreenWidth > mScreenHeight) {
            mScreenWidth
        } else {
            mScreenHeight
        }
        val mRateWidth = (mWidth * rate).toInt()
        return if (mRateWidth > mScreenWidth) {
            mScreenWidth
        } else {
            mRateWidth
        }
    }

    /**
     * 全屏
     */
    @JvmStatic
    fun fullScreen(window: Window?) {
        if (window == null) {
            return
        }
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
    }
}